﻿using System;
using System.Collections.Generic;
using System.Xml;
using System.IO;
using Common;
using System.Reflection;
using System.Windows.Forms;
namespace Model
{
   public class ServerExplorerDAO
    {

       /// <summary>
       /// 保存服务器连接等设置到配置文件
       /// </summary>
       /// <param name="xmlPath">要保存到的路径</param>
       /// <param name="menuConfig">配置信息实体类</param>
       /// <returns>0代表成功，1代表已经存在相同配置</returns>
       public static int SaveMenuConfigToXml(string xmlPath,string xmlName,exMenuConfigChild menuConfig)
       {
           try
           {
               XmlDocument xmlDoc = new XmlDocument();
               XmlNode rootNode = null;
               if (File.Exists(xmlPath+xmlName))//存在该配置文件则修改
               {
                   xmlDoc.Load(xmlPath+xmlName);
                   if (HasSameConfigName(enumXmlConfigType.MenuConfig, xmlDoc, menuConfig.ConfigName))
                   {
                       return 1;
                   }

                   rootNode = xmlDoc.SelectSingleNode("MenuConfig");
               }
               else//不存在该配置文件则新建
               {
                   //新建一个文件夹
                   FileIOHelper.CreateFolderFromPaths(xmlPath);
          
                   //添加XML文件声明
                   XmlNode dn = xmlDoc.CreateNode(XmlNodeType.XmlDeclaration, "", "");
                   xmlDoc.AppendChild(dn);
                   //添加根节点
                   rootNode = xmlDoc.CreateElement("MenuConfig");
                   xmlDoc.AppendChild(rootNode);
               }

               //添加每个配置的配置名用于区分每个配置
               XmlElement configName = xmlDoc.CreateElement("ConfigName");
               XmlAttribute configNameA = xmlDoc.CreateAttribute("Value");
               configNameA.Value = menuConfig.ConfigName;
               configName.Attributes.Append(configNameA);
               rootNode.AppendChild(configName);

               //用反射遍历每个属性，并添加进XML
               foreach (PropertyInfo pi in menuConfig.GetType().GetProperties())
               {
                   if (String.Compare(pi.Name, "ConfigName", false) != 0)
                   {
                       XmlElement xe = xmlDoc.CreateElement(pi.Name);
                       XmlText xt = null;
                       //布尔值在C#中是小写字母形式，默认写入XML文件时，第一个字母是大写，要转化成全部是小写字母再写入
                       xt = pi.PropertyType == typeof(Boolean) ? 
                           xmlDoc.CreateTextNode
                           (
                            String.IsNullOrEmpty(pi.GetValue(menuConfig, null).ToString()) ? "" : pi.GetValue(menuConfig, null).ToString().ToLower()
                           ) 
                           : 
                           xmlDoc.CreateTextNode
                           (
                            String.IsNullOrEmpty(pi.GetValue(menuConfig, null).ToString()) ? "" : pi.GetValue(menuConfig, null).ToString()
                           );

                       xe.AppendChild(xt);
                       configName.AppendChild(xe);
                   }
               }
               xmlDoc.Save(xmlPath+xmlName);
               return 0;
           }
           catch (Exception ex)
           {
             throw ex;
           }
       }


       /// <summary>
       /// 保存用于生成控件的信息
       /// </summary>
       /// <param name="xmlPath">需要保存到的路径</param>
       /// <param name="ConfigName">服务器连接信息配置名</param>
       /// <param name="fInfo">生成信息的实体类</param>
       /// <returns>0代表成功，1代表已经存在相同配置</returns>
       public static int SaveBuildInfoToXml(string xmlPath, string xmlName, string ConfigName, List<exFieldInfo> XmlInfoList)
       {

           try
           {
               XmlDocument xmlDoc = new XmlDocument();
               XmlNode rootNode = null;
               if (File.Exists(xmlPath + xmlName))//存在该配置文件则修改
               {
                   xmlDoc.Load(xmlPath + xmlName);
                   if (HasSameConfigName(enumXmlConfigType.BuildInfoConfig, xmlDoc, ConfigName))
                   {
                       return 1;
                   }

                   rootNode = xmlDoc.SelectSingleNode("BuildInformation");
               }
               else//不存在该配置文件则新建
               {
                   //新建一个文件夹
                   FileIOHelper.CreateFolderFromPaths(xmlPath);

                   //添加XML文件声明
                   XmlNode dn = xmlDoc.CreateNode(XmlNodeType.XmlDeclaration, "", "");
                   xmlDoc.AppendChild(dn);
                   //添加根节点
                   rootNode = xmlDoc.CreateElement("BuildInformation");
                   xmlDoc.AppendChild(rootNode);
               }

               //添加每个配置的配置名用于区分每个配置
               XmlElement configNameXE = xmlDoc.CreateElement("ConfigName");
               XmlAttribute configNameXEA = xmlDoc.CreateAttribute("Value");
               configNameXEA.Value = ConfigName;
               configNameXE.Attributes.Append(configNameXEA);
               rootNode.AppendChild(configNameXE);

               XmlInfoList.ForEach(xfi =>
               {
                   XmlElement tableNameXE = xmlDoc.CreateElement("Table");
                   XmlAttribute tableNameXEA = xmlDoc.CreateAttribute("Name");
                   tableNameXEA.Value = xfi.TableName;
                   tableNameXE.Attributes.Append(tableNameXEA);
                   configNameXE.AppendChild(tableNameXE);
                   //用反射遍历每个属性，并添加进Field节点的属性中
                   xfi.FieldInfoList.ForEach(xfic =>
                   {
                       XmlElement xe = xmlDoc.CreateElement("Field");
                       foreach (PropertyInfo pi in xfic.GetType().GetProperties())
                       {
                           XmlAttribute xa = xmlDoc.CreateAttribute(pi.Name);
                           xa.Value = String.IsNullOrEmpty(pi.GetValue(xfic, null).ToString()) ? "" : pi.GetValue(xfic, null).ToString();
                           xe.Attributes.Append(xa);
                       }
                       tableNameXE.AppendChild(xe);
                   });
               });
               xmlDoc.Save(xmlPath + xmlName);
               return 0;
           }
           catch (Exception ex)
           {
               throw ex;
           }
       }


       /// <summary>
       /// 读取所有保存的连接信息
       /// </summary>
       /// <param name="xmlPath">配置文件路径</param>
       /// <param name="tree">需要绑定的TreeView</param>
       public static void LoadMenuConfigToTree(string menuPath,string menuName,string buildPath,string buildName, TreeView tree,ImageList imgList)
       {
           if (File.Exists(menuPath + menuName) && File.Exists(buildPath + buildName))
           {
               XmlDocument menuDoc = new XmlDocument();
               menuDoc.Load(menuPath + menuName);
               XmlNodeList xeList = menuDoc.SelectNodes("//MenuConfig//ConfigName");
               foreach (XmlNode configName in xeList)
               {
                   //生成每个配置的根节点以配置名命名,每个根节点下有2个子节点
                   TreeNode rootNode = new TreeNode 
                   { Text = configName.Attributes["Value"].Value, 
                     Name = configName.Attributes["Value"].Value };

                   //生成根节点下的ServerInfo节点
                   TreeNode configNode = new TreeNode 
                   { Text = "Server Infomation", 
                     Name = "Server Infomation" };
                   foreach (XmlNode xn in configName.ChildNodes)
                   {
                       TreeNode childNode = new TreeNode 
                       { Text = String.Format("{0}:{1}", xn.Name, xn.InnerText), 
                         Name = String.Format("{0}:{1}", xn.Name, xn.InnerText) };
                       configNode.Nodes.Add(childNode);
                   }
                   rootNode.Nodes.Add(configNode);

                   //生成根节点下的Tables节点
                   TreeNode buildNode = new TreeNode 
                   { Text = "Tables", 
                     Name = "Tables" };
                   XmlDocument buildDoc = new XmlDocument();
                   buildDoc.Load(buildPath + buildName);
                   List<exFieldInfo> buildList = LoadBuildInfoByConfigName(buildDoc, rootNode.Name);
                   buildList.ForEach(exFI =>
                   {
                       TreeNode tableNode = new TreeNode 
                       { 
                           Text = exFI.TableName, 
                           Name = exFI.TableName 
                       };
                       exFI.FieldInfoList.ForEach(exFIC =>
                       {
                           TreeNode fieldNode = new TreeNode 
                           { 
                               Text = String.Format("{0}-{1}-{2}", exFIC.FieldName, exFIC.FieldType, exFIC.Description),
                               Name = String.Format("{0}-{1}-{2}", exFIC.FieldName, exFIC.FieldType, exFIC.Description) 
                           };
                           tableNode.Nodes.Add(fieldNode);
                       });
                       buildNode.Nodes.Add(tableNode);
                   });
                   rootNode.Nodes.Add(buildNode);
                  
                   
                   tree.Nodes.Add(rootNode);
               }
           }
       }


       /// <summary>
       /// 返回一个配置下的菜单信息
       /// </summary>
       /// <param name="menuDoc">配置文件MenuConfig.xml的XmlDocument对象，不传path是为了防止对磁盘的多次I/O操作</param>
       /// <param name="configName">配置名称</param>
       /// <returns></returns>
       public static List<exMenuConfigChild> LoadMenuConfigByConfigName(XmlDocument menuDoc, string configName)
       {
           List<exMenuConfigChild> list = null;
           try
           {
               list = new List<exMenuConfigChild>();
               exMenuConfigChild exMCC;
               foreach (XmlNode xn in menuDoc.SelectNodes("//MenuConfig//ConfigName"))
                   {
                       if (!xn.Attributes["Value"].Value.Equals(configName))
                           continue;

                       exMCC = new exMenuConfigChild();
                       foreach (XmlNode xnChild in xn.ChildNodes)
                       {
                           exMCC.ConfigName = configName;
                           switch (xnChild.Name)
                           {
                               case "ConnectString": exMCC.ConnectString = xnChild.InnerText;
                                   break;
                               case "QueryString": exMCC.QueryString = xnChild.InnerText;
                                   break;
                               case "IsQueryType": exMCC.IsQueryType = Boolean.Parse(xnChild.InnerText);
                                   break;
                               case "DataBase": exMCC.DataBase = xnChild.InnerText;
                                   break;
                               case "HasWinForm": exMCC.HasWinForm = Boolean.Parse(xnChild.InnerText);
                                   break;
                               case "HasASPNET": exMCC.HasASPNET = Boolean.Parse(xnChild.InnerText);
                                   break;
                               case "HasDevExpree": exMCC.HasDevExpree = Boolean.Parse(xnChild.InnerText);
                                   break;
                               case "HasWPFHasWPF": exMCC.HasWPF = Boolean.Parse(xnChild.InnerText);
                                   break;
                               case "HasMicrosoft": exMCC.HasMicrosoft = Boolean.Parse(xnChild.InnerText);
                                   break;
                               case "HasDevLayout": exMCC.HasDevLayout = Boolean.Parse(xnChild.InnerText);
                                   break;
                               case "IsBuildTable": exMCC.IsBuildTable = Boolean.Parse(xnChild.InnerText);
                                   break;
                               case "IsBuildFieldTable": exMCC.IsBuildFieldTable = Boolean.Parse(xnChild.InnerText); ;
                                   break;
                           }
                                 list.Add(exMCC);
                       }
                       break;
                   }
           }
           catch (Exception ex)
           {
               throw ex;
           }
           return list;
       }


       /// <summary>
       /// 返回一个配置下的生成信息(一个exFieldInfo为一张表)
       /// </summary>
       /// <param name="buildDoc">配置文件BuildInfo.xml的XmlDocument对象，不传path是为了防止对磁盘的多次I/O操作<param>
       /// <param name="configName">配置名称</param>
       /// <returns></returns>
       public static List<exFieldInfo> LoadBuildInfoByConfigName(XmlDocument buildDoc,string configName)
       {
           List<exFieldInfo> list=null;
           try
           {
                   list=new List<exFieldInfo>();
                   exFieldInfo exFI;
                   List<exFieldInfoChild> listChild;
                   exFieldInfoChild exFIChild;
                   foreach (XmlNode xn in buildDoc.SelectNodes("//BuildInformation//ConfigName"))
                   {
                       if (!xn.Attributes["Value"].Value.Equals(configName))
                           continue;

                       listChild = new List<exFieldInfoChild>();
                       foreach (XmlNode xnTable in xn.ChildNodes)
                       {
                           exFI = new exFieldInfo();
                           listChild = new List<exFieldInfoChild>();
                           exFI.TableName = xnTable.Attributes["Name"].Value;
                           foreach (XmlNode xnField in xnTable.ChildNodes)
                           {
                               exFIChild = new exFieldInfoChild();
                               exFIChild.FieldName = xnField.Attributes["FieldName"].Value;
                               exFIChild.FieldType = xnField.Attributes["FieldType"].Value;
                               exFIChild.Description = xnField.Attributes["Description"].Value;
                               listChild.Add(exFIChild);
                           }
                           exFI.FieldInfoList = listChild;
                           list.Add(exFI);
                       }
                       break;
                   }
           }
           catch (Exception ex)
           {
               throw ex;
           }
           return list;
       }

       

       /// <summary>
       /// 判断是不是有相同配置名存在
       /// </summary>
       /// <param name="doc"></param>
       /// <param name="ConfigName">配置名</param>
       /// <param name="configType">配置类型（菜单设置或者生成信息设置）</param>
       /// <returns></returns>
       public static bool HasSameConfigName( enumXmlConfigType configType, XmlDocument doc, string ConfigName)
       {  
           XmlNode xn=null;
           switch(configType)
           {
               case enumXmlConfigType.BuildInfoConfig:
                   xn = doc.SelectSingleNode("BuildInformation");
                   foreach (XmlNode xnChild in xn.ChildNodes)
                   {
                       if (String.Compare(xnChild.Attributes["Value"].Value, ConfigName, false) == 0 || xnChild.Attributes["Value"].Value.Equals(ConfigName))
                       {
                           return true;
                       }
                   }
                   return false;
               case enumXmlConfigType.MenuConfig:
                   xn = doc.SelectSingleNode("MenuConfig");
                   foreach (XmlNode xnChild in xn.ChildNodes)
                   {
                       if (String.Compare(xnChild.Attributes["Value"].Value, ConfigName, false) == 0 || xnChild.Attributes["Value"].Value.Equals(ConfigName))
                       {
                           return true;
                       }
                   }
                   return false;
               default:
                   return false;
           }

          
        
       }


       /// <summary>
       /// 通过配置名获取配置下的生成信息(跳过了Table节点)
       /// </summary>
       /// <param name="xmlPath">生成信息配置文件</param>
       /// <param name="ConfigName">配置名（树的根节点）</param>
       /// <returns></returns>
       public static List<exFieldInfoChild> GetBuildFieldInfoByConfigName(string xmlPath,string xmlName,string ConfigName)
       {
           List<exFieldInfoChild> list=new List<exFieldInfoChild>();
           
           try
           {
               exFieldInfoChild fic=null;
               XmlDocument doc = new XmlDocument();
               doc.Load(xmlPath+xmlName);
               foreach(XmlNode xn in doc.SelectNodes("//BuildInformation//ConfigName"))
               {
                   if (String.Compare(xn.Attributes["Value"].Value, ConfigName, false) != 0)
                       continue;

                   foreach (XmlNode xnn in xn.ChildNodes)//定位到Table节点
                   {
                       foreach (XmlNode xnnChild in xnn.ChildNodes)//定位到Field节点
                       {
                           fic = new exFieldInfoChild();
                           fic.FieldName = xnnChild.Attributes["FieldName"].Value;
                           fic.FieldType = xnnChild.Attributes["FieldType"].Value;
                           fic.Description = xnnChild.Attributes["Description"].Value;
                           list.Add(fic);
                       }
                   }
                   break;
                   
               }
           }
           catch(Exception ex)
           {
               throw ex;
           }
           return list;
       }


       /// <summary>
       /// 获取控件的缩写名称
       /// </summary>
       /// <param name="doc">配置文件路径</param>
       /// <param name="ControlType">控件的类型（TextBox,Label等）</param>
       /// <param name="ControlClass">控件的种类（WinForm，DevExpress等）</param>
       /// <returns></returns>
       public static string GetPrefixOfControl(XmlDocument doc,string ControlType,string ControlClass)
       {
          string prefix = "";
           try
           {

               XmlNode xn = doc.SelectSingleNode("//ControlPrefix//" + ControlClass);
               
               foreach (XmlNode childXN in xn)
               {
                   if (String.Compare(childXN.Attributes["Type"].Value, ControlType, false) != 0)
                       continue;

                   prefix = childXN.Attributes["Prefix"].Value;
                   break;
                   
               }
              
           } 
           
           catch(Exception ex)
           {
               throw ex;
           }
          return prefix;
       }


       /// <summary>
       /// 从配置文件获取字段类型跟控件的对应关系
       /// </summary>
       /// <param name="doc">字段类型与控件对应关系配置文件的XmlDocument对象</param>
       /// <param name="doc2">控件与控件缩写前缀配置文件的XmlDocument对象</param>
       /// <param name="FieldType">字段类型</param>
       public static List<exControlInfo> GetControlListByFieldType(XmlDocument doc, XmlDocument doc2, string fieldType)
       {
         
          List<exControlInfo> list = null;
          try
          {

              XmlNode fieldXN = null;
             
              list = new List<exControlInfo>();
              exControlInfo cinfo = null;
              foreach (XmlNode xn in doc.SelectNodes("//FieldToControlConfig//Field"))
              {
                  if (String.Compare(xn.Attributes["Type"].Value, fieldType, false) != 0)
                      continue;
                    
                  fieldXN = xn;
                  break;
              }
              foreach (XmlNode childXN in fieldXN.ChildNodes)
              {
                  cinfo = new exControlInfo();
                  //将字符串转化成枚举类型
                  //cinfo.ControlClass = (enumControlClass)Enum.Parse(typeof(enumControlClass), childXN.Attributes["Class"].Value);
                  cinfo.ControlClass = childXN.Attributes["Class"].Value;
                  cinfo.ControlType = childXN.Attributes["Type"].Value;
                  cinfo.Prefix = GetPrefixOfControl(doc2, cinfo.ControlType, cinfo.ControlClass);
                  list.Add(cinfo);
              }
    
          }
          catch (Exception ex)
          {
              throw ex;
          }
          return list;
      }

 
       /// <summary>
       /// 删除菜单配置
       /// </summary>
       /// <param name="ConfigName"></param>
       public static void DeleteMenuConfig(string ConfigName)
       {
           try
           {
               XmlDocument doc = new XmlDocument();
               doc.Load(PubConstant.ConfigPath+PubConstant.ServerMenuConfigName);
               XmlNode xn = doc.SelectSingleNode("//MenuConfig");
               foreach (XmlNode xnChild in xn.ChildNodes)
               {
                   if (!xnChild.Attributes["Value"].Value.Equals(ConfigName))
                       continue;

                   xn.RemoveChild(xnChild);
                   break;
               }
               doc.Save(PubConstant.ConfigPath + PubConstant.ServerMenuConfigName);
           }
           catch (Exception ex)
           { throw ex; }
       }
      
       /// <summary>
       /// 删除生成信息
       /// </summary>
       /// <param name="ConfigName"></param>
       public static void DeleteBuildInfo(string ConfigName)
       {
           try
           {
               XmlDocument doc = new XmlDocument();
               doc.Load(PubConstant.ConfigPath+PubConstant.ServerBuildConfigName);
               XmlNode xn = doc.SelectSingleNode("//BuildInformation");
               foreach (XmlNode xnChild in xn.ChildNodes)
               {
                   if (!xnChild.Attributes["Value"].Value.Equals(ConfigName))
                       continue;

                   xn.RemoveChild(xnChild);
                   break;
               }
               doc.Save(PubConstant.ConfigPath+PubConstant.ServerBuildConfigName);
           }
           catch (Exception ex)
           { throw ex; }
       }
    }
}
